package com.alipay.controller.interfaced;



import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.service.interfaced.AlipayInManager;
import com.alipay.util.AliPayConfig;
import com.business.service.interfaced.EntertainmentInManager;
import com.business.service.interfaced.StandardInManager;
import com.business.service.interfaced.impl.HighEntertainInService;
import com.honour.service.interfaced.CartInManager;
import com.honour.service.interfaced.OrderManager;
import com.honour.service.interfaced.SortInManager;
import com.system.common.OrderEnum;
import com.system.common.PayType;
import com.system.controller.base.BaseController;
import com.system.property.ZfbProperty;
import com.system.util.AppUtil;
import com.system.util.DateUtil;
import com.system.util.PageData;
import com.system.util.Tools;


/**
 * 阿里支付接口
 * @Function 
 * @Author zhaozhenhua
 * @Date 2018年4月20日
 */
@Controller
@RequestMapping("/zfbalipay")
public class AlipayInController extends BaseController{
	
	
	
	
	
	@Resource(name = "orderService")
	private OrderManager orderService;
	
	@Resource(name = "alipayInManager")
	private AlipayInManager alipayInService;
	
	@Resource(name="standardInService")
	private StandardInManager standardInService;
	
	@Resource(name = "cartInService")
	private CartInManager cartInService;
	
	@Resource(name="highEntertainInService")
	private HighEntertainInService highEntertainInService;
	
	@Resource(name="entertainmentInService")
	private EntertainmentInManager entertainmentInService;
	
	@Resource(name="sortinService")
	private SortInManager sortinService;
	
	
	
	
	/**
	 * TODO 支付通知(支付宝后台的回调通知)
	  * @Description
	  * @Author zhaozhenhua
	  * @date   2018年5月4日
	  * @param pd
	  * @return 必须返回success后failure
	  * @throws Exception
	 */
	@RequestMapping("alipaynotify")
	public String aliPayNotify(HttpServletRequest request){
		logBefore(logger, "TODO 支付通知(支付宝后台的回调通知) ");
		//商户处理后同步返回给微信参数：
		String success = "success";
		String failure = "failure";
		
		PageData pd = new PageData();
		pd = this.getPageData();
		try{
			//if(Tools.checkKey("ALIPAYNOTIFY", pd.getString("FKEY"))){	//检验请求key值是否合法
				//获取支付宝POST过来反馈信息
				 Map<String,String> receiveMap = getReceiveMap(request);
				 logger.info("支付宝支付回调参数=="+receiveMap);
				 //在通知返回参数列表中，除去sign_type参数
				 receiveMap.remove("sign_type");
				 //验证签名
				 //boolean signVerified = AliPayUtil.rsaCheck(receiveMap);
				 boolean signVerified = AlipaySignature.rsaCheckV2(receiveMap, ZfbProperty.get("alipay_public_key"), "utf-8",ZfbProperty.get("sign_type")); //调用SDK验证签名
				 logger.info("验证签名:"+signVerified);
				 if(!signVerified){
			         return failure;
				 }
				
				 
				// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)
			    // 1,判断是否有异步通知
				/* if(Tools.isEmpty(receiveMap.get("notify_id"))){
			            logger.info("支付宝支付回调没有异步通知");
			            map.put("pd", "支付宝支付回调没有异步通知");
			            return "no notify message";
			     }*/
				 //2,判断是否是支付宝发来的异步通知
		        /*if(!AliPayUtil.verifyResponse(receiveMap.get("notify_id")).equals("true")){  
		            System.out.println("支付宝支付回调通知错误");
		            map.put("pd", "支付宝支付回调通知错误");
		            return ("response failure");
		        }*/
		        //3,判断是否是支付宝发来的异步通知
		       /* if(!AliPayUtil.rsaCheck(receiveMap)){
		            System.out.println("支付宝支付回调验证签名失败");
		            map.put("pd", "支付宝支付回调验证签名失败");
		            return "sign failure";
		        }*/
		        
		       //4,判断交易状态
		        String tradeStatus = receiveMap.get("trade_status");
		        String ORDERTYPE = receiveMap.get("body");
		        System.out.println("交易状态:"+tradeStatus);
		        if ("TRADE_FINISHED".equals(tradeStatus) || "TRADE_SUCCESS".equals(tradeStatus)){
		            String out_trade_no = receiveMap.get("out_trade_no");    // 商户订单号
		            System.out.println("支付宝支付回调商户订单号=="+out_trade_no);
		            
		            //防止支付宝重复通知
		 	        pd.put("ORDERNUMBER", out_trade_no);
		 	        try {
						PageData payInfo = alipayInService.getPayInfo(pd);
						if(payInfo != null){
							return success;
						}
					} catch (Exception e1) {
						e1.printStackTrace();
					}
		 	       //订单业务操作
		            //查询订单,修改子订单表状态，减库存,加商品销售数量,修改订单表支付时间
		 	       PageData order = new PageData();
		 	       switch (ORDERTYPE) {
		 	       case "1"://订单类型为美食
		 	    	    logger.info("TODO 支付通知(支付宝后台的回调通知)---美食订单");
						order = entertainmentInService.getFoodOrderByNum(pd);
						pd.put("ORDERPAYTIME", receiveMap.get("gmt_payment"));//交易创建时间
					    pd.put("ORDERSTATUS", "0040002");//待使用
						pd.put("HONOURUSER_ID", order.get("HONOURUSER_ID"));
						pd.put("ORDEROTHERNUM", receiveMap.get("trade_no"));//支付宝交易号
						sortinService.updFoodOrderStatus(pd);
						//插入订单支付信息
						addZFBPayInfo(pd,receiveMap,order);
						return success;
					case "2"://订单类型为酒店
						logger.info("TODO 支付通知(支付宝后台的回调通知)---酒店订单");
						order = entertainmentInService.getHotelOrderByNum(pd);
						pd.put("ORDERPAYTIME", receiveMap.get("gmt_payment"));//交易创建时间
					    pd.put("ORDERSTATUS", "0040002");//待使用
						pd.put("HONOURUSER_ID", order.get("HONOURUSER_ID"));
						pd.put("ORDEROTHERNUM", receiveMap.get("trade_no"));//支付宝交易号
						sortinService.updHotelOrderStatus(pd);
						//插入订单支付信息
						addZFBPayInfo(pd,receiveMap,order);
						return success;
					case "3"://订单类型为KTV
						logger.info("TODO 支付通知(支付宝后台的回调通知)---KTV订单");
						order = entertainmentInService.getKTVOrderByNum(pd);
						pd.put("ORDERPAYTIME", receiveMap.get("gmt_payment"));//交易创建时间
					    pd.put("ORDERSTATUS", "0040002");//待使用
						pd.put("HONOURUSER_ID", order.get("HONOURUSER_ID"));
						pd.put("ORDEROTHERNUM", receiveMap.get("trade_no"));//支付宝交易号
						sortinService.updKTVOrderStatus(pd);
						//插入订单支付信息
						addZFBPayInfo(pd,receiveMap,order);
						return success;
					case "4"://订单类型为酒吧
						logger.info("TODO 支付通知(支付宝后台的回调通知)---酒吧订单");
						order = entertainmentInService.getBarOrderByNum(pd);
						pd.put("ORDERPAYTIME", receiveMap.get("gmt_payment"));//交易创建时间
					    pd.put("ORDERSTATUS", "0040002");//待使用
						pd.put("HONOURUSER_ID", order.get("HONOURUSER_ID"));
						pd.put("ORDEROTHERNUM", receiveMap.get("trade_no"));//支付宝交易号
						sortinService.updBarOrderStatus(pd);
						//插入订单支付信息
						addZFBPayInfo(pd,receiveMap,order);
						return success;
					case "5"://订单类型为马术
						logger.info("TODO 支付通知(支付宝后台的回调通知)---马术订单");
						order = highEntertainInService.getHighOrderByNo(pd);
						updHighOrder(pd, receiveMap, order);
						return success;
					case "6"://订单类型为游艇
						logger.info("TODO 支付通知(支付宝后台的回调通知)---游艇订单");
						order = highEntertainInService.getHighOrderByNo(pd);
						updHighOrder(pd, receiveMap, order);
						return success;
					case "7"://订单类型为豪车
						logger.info("TODO 支付通知(支付宝后台的回调通知)---豪车订单");
						order = highEntertainInService.getHighOrderByNo(pd);
						updHighOrder(pd, receiveMap, order);
						return success;
					case "8"://订单类型为飞机
						logger.info("TODO 支付通知(支付宝后台的回调通知)---飞机订单");
						order = highEntertainInService.getHighOrderByNo(pd);
						updHighOrder(pd, receiveMap, order);
						return success;
					case "9"://订单类型为高尔夫
						logger.info("TODO 支付通知(支付宝后台的回调通知)---高尔夫订单");
						order = highEntertainInService.getHighOrderByNo(pd);
						updHighOrder(pd, receiveMap, order);
						return success;
					case "50"://订单类型为尊购商品
						//查询订单,修改子订单表状态，减库存,加商品销售数量,修改订单表支付时间
						logger.info("TODO 支付通知(支付宝后台的回调通知)---尊购商品订单");
						order.put("ORDERSTATUS", "待发货");
		            	orderService.updateOrderStatus(order);
		            	
		            	//从购物车中移除商品
		            	order.put("CHECKED", 1);
		            	List<PageData> cartList = cartInService.selectProductByUserIdAndChecked(order);
		            	//将购物车中的商品的规格id和数量放入mapCart中
						Map<String, Object> mapCart = new HashMap<>();
		            	for (PageData cart : cartList) {
		            		mapCart.put(cart.getString("STANDARD_ID"), cart.get("QUANTITY"));
		            		cartInService.delete(cart);
		            	}
		            	
		            	
		            	List<PageData> stockByNum = orderService.getStockByNum(order);
		            	for (PageData p : stockByNum) {
		            		Integer PRO_STOCK = p.getInterger("PRO_STOCK");
		            		PRO_STOCK = PRO_STOCK-(Integer)mapCart.get(p.getString("STANDARD_ID"));
							p.put("PRO_STOCK", PRO_STOCK);
		            		standardInService.edit(p);
		            	}
		            	
		            	order.put("PAY_TIME", receiveMap.get("notify_time"));
		            	order.put("PAYTYPE", 1);
		            	orderService.updateOrder(order);
		            	//插入订单支付信息
		            	addZFBPayInfo(pd, receiveMap, order);
		            	return success;
					default:
						break;
					}
		            
		            //、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
		           /* if(!receiveMap.get("out_trade_no").equals(o.get("ORDERNUMBER"))){
		            	logger.info("验证该通知数据中的out_trade_no是否为商户系统中创建的订单号错误");
		            	return failure;
		            }*/
		            
		            //2、判断total_amount是否确实为该订单的实际金额
		            /*if(receiveMap.get("total_amount").equals(o.get("ORDERMONEY"))){
		            	logger.info("total_amount是否确实为该订单的实际金额错误");
		            	return failure;
		            }*/
		            
		            //3校验通知中的seller_id是否为out_trade_no这笔单据的对应的操作方
		            //4.验证app_id是否为该商户本身
		            /*if(!receiveMap.get("seller_id").equals(ZfbProperty.get("pid"))||!receiveMap.get("app_id").equals(ZfbProperty.get("appid"))){
		            	logger.info("验通知中的seller_id是否为out_trade_no这笔单据的对应的操作方错误");
		            	return failure;
		            }*/
		            
		        }
		        logger.info("支付宝支付回调失败");
			/*}else{
				result = "05";
			}*/
		}catch (Exception e){
			logger.error(e.toString(), e);
		}finally{
			logAfter(logger);
		}
		 return failure;
	}
	
	
	
	/**
	 * 获取请求参数 
	  * @Description
	  * @Author zhaozhenhua
	  * @date   2018年5月4日
	  * @param pd
	  * @return
	  * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private static Map<String,String> getReceiveMap(HttpServletRequest request){
	        Map<String,String> receiveMap = new HashMap<String,String>();
	        Map<String, String[]> requestParams = request.getParameterMap();
	        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
	            String name = iter.next();
	            String[] values = requestParams.get(name);
	            String valueStr = "";
	            for (int i = 0; i < values.length; i++) {
	                valueStr = (i == values.length - 1) ? valueStr + values[i]
	                            : valueStr + values[i] + ",";
	            }
	            //乱码解决，这段代码在出现乱码时使用
	           /* try {
					valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}*/
	            receiveMap.put(name, valueStr);
	        }
	        return receiveMap;
	    }
	
	
	/**
	 * 查询支付信息
	  * @Description
	  * @Author zhaozhenhua
	  * @date   2018年2月26日
	  * @param pd
	  * @return
	  * @throws Exception
	 */
	@RequestMapping("getPayInfo")
	@ResponseBody
	public Object getPayInfo(){
		logBefore(logger, "查询支付信息 ");
		Map<String,Object> map = new HashMap<String,Object>();
		PageData pd = new PageData();
		pd = this.getPageData();
		String result = "00";
		try{
			if(Tools.checkKey("GETPAYINFO", pd.getString("FKEY"))){	//检验请求key值是否合法
				if(AppUtil.checkParam("pay", pd)){	//检查参数
					PageData payInfo = alipayInService.getPayInfo(pd);
					if(null == payInfo){
						result = "01";
						map.put("pd", "下单失败");
						return AppUtil.returnObject(new PageData(), map);
					}
//					PageData address = orderService.selectAdrByUserIdAndStatus(pd);
//					payInfo.put("USERNAME", address.get("CONSIGNEE"));
//					payInfo.put("ADRPHONE", address.get("ADRPHONE"));
//					payInfo.put("ADDRESS", address.getString("PROVINCE")+address.getString("ADDRESS"));
					map.put("pd", "下单成功");
					result = "01";
					//map.put("pd", payInfo);
				}else {
					result = "03";
				}
			}else{
				result = "05";
			}
		}catch (Exception e){
			logger.error(e.toString(), e);
		}finally{
			map.put("result", result);
			logAfter(logger);
		}
		return AppUtil.returnObject(new PageData(), map);
	}
	
	 /**
	  * 添加支付宝订单支付信息
	   * @Description
	   * @Author zhaozhenhua
	   * @date   2018年5月11日
	   * @param pd
	   * @param params
	   * @param order
	   * @param time_end
	  */
	 public void addZFBPayInfo(PageData pd,Map<String,String> receiveMap,PageData order){
		//插入订单支付信息
     	pd.put("PAYINFO_ID", this.getSnowId());
     	pd.put("PLATFORM_NUMBER", receiveMap.get("trade_no"));//支付宝交易号
     	pd.put("PLATFORM_STATUS", receiveMap.get("trade_status"));//交易状态
     	pd.put("PAY_PLATFORM", PayType.ALI.getCode());
     	pd.put("ORDERNUMBER", receiveMap.get("out_trade_no"));
     	pd.put("CREATE_TIME", receiveMap.get("gmt_payment"));//交易付款时间
     	pd.put("HONOURUSER_ID", order.get("HONOURUSER_ID"));
     	pd.put("ORDERMONEY", receiveMap.get("total_amount"));
     	pd.put("ORDERTYPE", receiveMap.get("body"));
		try {
			alipayInService.addPayInfo(pd);
		} catch (Exception e) {
			e.printStackTrace();
		}
	 }    
	 
	 /**
	  * 修改高端特权订单状态
	   * @Description
	   * @Author zhaozhenhua
	   * @date   2018年5月15日
	   * @param pd
	   * @return
	   * @throws Exception
	  */
	 public void updHighOrder(PageData pd,Map<String, String> receiveMap,PageData order){
     	pd.put("ORDERPAYTIME", receiveMap.get("gmt_payment"));//交易创建时间
     	pd.put("ORDERSTATUS", "0040002");
     	pd.put("HIGHENTERORDER_ID", order.get("HIGHENTERORDER_ID"));
     	pd.put("ORDEROTHERNUM", receiveMap.get("trade_no"));//支付宝交易号
     	try {
			highEntertainInService.updHighOrder(pd);
			//插入订单支付信息
			addZFBPayInfo(pd, receiveMap, order);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}  
	 
	 
	 /**支付宝退款 接口
		 * @Author: zhaozhenhua
		 * @Description: 支付宝退款 退款的金额 不能大于交易金额
		 * store_id 可选 代表 商户的门店编号
		 * terminal_id 可选 代表 商户的终端编号
		 * operator_id 可选 代表 商户的操作员编号
		 * refund_reason 可选 代表 退款的原因说明
		 * out_request_no 可选 标识一次退款请求，同一笔交易多次退款需要保证唯一（就是out_request_no在2次退款一笔交易时，要不一样），如需部分退款，则此参数必传
		 * trade_no 必须 支付宝交易号
		 * out_trade_no 必须 商户订单号
		 * refund_amount 必须 退款金额
		 */
		 @ResponseBody
		 @RequestMapping(value = "aliPayRefund")
		 public Object alipayRefundRequest(){
			 logBefore(logger, "支付宝退款 接口 ");
			 Map<String,Object> map = new HashMap<String,Object>();
			 PageData pd = new PageData();
			 pd = this.getPageData();
			 String result = "00";
			 try{
					if(Tools.checkKey("ALIPAYREFUND", pd.getString("FKEY"))){	//检验请求key值是否合法
						if(AppUtil.checkParam("aliPayRefund", pd)){	//检查参数
							//判断是否为重复操作
							PageData refundByNum = alipayInService.getRefundByNum(pd);
							if(refundByNum==null){
								//先生成自己系统退款订单
								pd.put("REFUND_ID", this.getSnowId());
								pd.put("REFUND_TIME", DateUtil.getTime());
								pd.put("PAY_PLATFORM", PayType.ALI.getCode());
								pd.put("REFUND_FEE", pd.get("ORDERMONEY"));
								alipayInService.addRefundInfo(pd);
							}
							
							AlipayTradeRefundResponse response = alipayRefund(pd); 
							 if (response.isSuccess()) {
								 System.out.println("调用成功");
								 Date date = response.getGmtRefundPay();
								 String dateToString = DateUtil.dateToString(date);
								 pd.put("REFUND_PAY_TIEM", dateToString);//gmt_refund_pay退款支付时间
								 pd.put("FUND_CHANGE", response.getFundChange());//fund_change本次退款是否发生了资金变化
							     pd.put("BUYER_USER_ID", response.getBuyerUserId());//buyer_user_id买家在支付宝的用户id
							     alipayInService.updRefund(pd);
							     //修改订单的状态
							     String ORDERTYPE = pd.getString("ORDERTYPE");
							     switch (ORDERTYPE) {
								case "1":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									sortinService.updFoodOrderStatus(pd);
									break;
								case "2":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									sortinService.updHotelOrderStatus(pd);
									break;
								case "3":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									sortinService.updKTVOrderStatus(pd);
									break;
								case "4":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									sortinService.updBarOrderStatus(pd);
									break;
								case "5":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									highEntertainInService.updHighOrder(pd);
									break;
								case "6":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									highEntertainInService.updHighOrder(pd);
									break;
								case "7":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									highEntertainInService.updHighOrder(pd);
									break;
								case "8":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									highEntertainInService.updHighOrder(pd);
									break;
								case "9":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									highEntertainInService.updHighOrder(pd);
									break;
								case "10":
									pd.put("ORDERSTATUS", OrderEnum.REFUND.getCode());
									highEntertainInService.updHighOrder(pd);
									break;
								case "50":
									pd.put("ORDERSTATUS", "已退款");
					            	orderService.updateOrderStatus(pd);
									break;
									
								default:
									break;
								}
							     result = "01";
							 } else {
								 System.out.println("调用失败");
								 result = "02";
							 }
						}else {
							result = "03";
						}
					}else{
						result = "05";
					}
				}catch (Exception e){
					logger.error(e.toString(), e);
				}finally{
					map.put("result", result);
					logAfter(logger);
				}
			return AppUtil.returnObject(new PageData(), map);
			
		 }
		 
		 public AlipayTradeRefundResponse alipayRefund(PageData pd){
			 AlipayClient alipayClient = AliPayConfig.getAlipayClient();
			//实例化具体API对应的request类
			AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		    PageData aliPd = new PageData();
		    //支付宝交易号，和商户订单号不能同时为空
		    aliPd.put("trade_no", pd.get("ORDEROTHERNUM"));
		    //订单支付时传入的商户订单号,不能和 trade_no同时为空。
		    aliPd.put("out_trade_no", pd.get("ORDERNUMBER"));
		    aliPd.put("refund_amount", pd.get("ORDERMONEY"));
		    String json = JSONObject.toJSONString(aliPd);
		    logger.info("BizContent-json:"+json);
		    request.setBizContent(json);
			try {
				AlipayTradeRefundResponse response = alipayClient.execute(request);
				return response;
			} catch (AlipayApiException e) {
				e.printStackTrace();
			}
			return null;
		 }
     

}
